﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;
using System.Xml.XPath;
using System.Xml;
using System.IO;
using MySQLStudio.Common.Data;

namespace MySQLStudio.Common
{
    public class DataUtils
    {
        private static DbDataTypeCollection dataTypes;

        // Join that takes an IEnumerable list that uses a converter to convert the type to a string
        public static string Join<T>(string separator, IEnumerable<T> list, Converter<T, string> converter)
        {
            StringBuilder sb = new StringBuilder();
            if (list != null)
            {
                foreach (T t in list)
                {
                    if (sb.Length != 0) sb.Append(separator);
                    sb.Append(converter(t));
                }
            }

            return sb.ToString();
        }


        // Join that takes an IEnumerable list that uses a converter to convert the type to a string
        public static W[] ListToPropertiesArray<T, W>(IList<T> list, Converter<T, W> converter)
        {
            W[] array = null;
            if (list != null)
            {
                array = new W[list.Count];
                int counter = 0;

                foreach (T t in list)
                {
                    array[counter] = converter(t);
                    counter++;
                }
            }

            return array;
        }


        //========================================================== methods

        public static string GetNullableString(IDataReader reader, int col)
        {
            if (reader.IsDBNull(col) == false)
                return reader.GetString(col);

            return null;
        }

        public static string GetNullableString(IDataReader reader, string columnName)
        {
            int columnOrdinal = reader.GetOrdinal(columnName);
            if (columnOrdinal > 0 && !reader.IsDBNull(columnOrdinal))
                return reader.GetString(columnOrdinal);

            return null;
        }

        

        public static string GetNullableString(DataRow row, int col)
        {
            if (row[col] != DBNull.Value && row[col] != null)
                return Convert.ToString(row[col]);

            return null;
        }

        public static DateTime? GetNullableDateTime(IDataReader reader, int col)
        {
            if (reader.IsDBNull(col) == false)
            {
                return reader.GetDateTime(col);
            }

            return null;
        }

        public static DateTime? GetNullableDateTime(IDataReader reader, string columnName)
        {
            int columnOrdinal = reader.GetOrdinal(columnName);
            if (reader.IsDBNull(columnOrdinal) == false)
                return reader.GetDateTime(columnOrdinal);

            return null;
        }

        public static DateTime? GetNullableDateTime(DataRow row, int col)
        {
            if (row[col] != DBNull.Value && row[col] != null)
                return Convert.ToDateTime(row[col]);

            return null;
        }

        public static int? GetNullableInt(IDataReader reader, int col)
        {
            if (reader.IsDBNull(col) == false)
            {
                return reader.GetInt32(col);
            }

            return null;
        }

        public static int? GetNullableInt(IDataReader reader, string columnName)
        {
            int ordinal = reader.GetOrdinal(columnName);
            if (ordinal >= 0)
            {
                if (reader.IsDBNull(ordinal) == false)
                    return reader.GetInt32(ordinal);
            }

            return null;
        }

        public static int? GetNullableInt(DataRow row, int col)
        {
            if (row[col] != DBNull.Value && row[col] != null)
                return Convert.ToInt32(row[col]);

            return null;
        }

        public static DbDataTypeCollection DataTypes
        {
            get
            {
                if (dataTypes == null || dataTypes.Count == 0)
                {
                    XmlDocument doc = new XmlDocument();                    

                    using (Stream stream = Assembly.GetExecutingAssembly()
                            .GetManifestResourceStream("MySQLStudio.Common.Data.DataTypes.xml"))
                    {
                        doc.Load(stream);
                    }

                    dataTypes = new DbDataTypeCollection();
                    XmlNodeList xmlTypes = doc.SelectNodes("//type");                    

                    foreach (XmlNode xmlType in xmlTypes)
                    {
                        XmlNode xmlLength = xmlType.SelectSingleNode("./length");
                        XmlNode xmlPrecision = xmlType.SelectSingleNode("./precision");
                        XmlNode xmlScale = xmlType.SelectSingleNode("./scale");


                        string name = xmlType.Attributes["name"].Value;
                        bool enablelength = Convert.ToBoolean(xmlType.Attributes["enablelength"].Value);
                        bool enableprecision = Convert.ToBoolean(xmlType.Attributes["enableprecision"].Value);
                        bool enablescale = Convert.ToBoolean(xmlType.Attributes["enablescale"].Value);
                        bool enablecollation = Convert.ToBoolean(xmlType.Attributes["enablecollation"].Value);
                        ulong? length = null;
                        ulong? precision = null;
                        ulong? scale = null;

                        if (xmlLength != null)
                        {
                            length = ulong.Parse(xmlLength.InnerText);
                        }

                        if (xmlPrecision != null)
                        {
                            precision = ulong.Parse(xmlPrecision.InnerText);
                        }

                        if (xmlScale != null)
                        {
                            scale = ulong.Parse(xmlScale.InnerText);
                        }

                        DbDataType dataType = new DbDataType(name, enablelength, enableprecision, enablescale, enablecollation,
                            length, precision, scale);

                        dataTypes.Add(dataType);
                    }

                    dataTypes.Sort();
                }

                return dataTypes;
            }
        }
    }
}
